import { Button, showModal } from '../../functionalComponent';
import { getGlobalConfig, OType, iup, type IObject } from '../../util';
import { ConvertListHelp } from './cpts/ConvertListHelp';
import { FlowHelp } from './cpts/FlowHelp';
import { ShowCheckRuleInfo } from './cpts/ShowCheckRuleInfo';
import { SourceHelp } from './cpts/SourceHelp';
import type {
  ArrayReturnType,
  ICheckRuleInfoParams,
  ICiteSourceParams,
  IFlowParams,
  IPushBillParams,
  IShowFlowInstance,
  MappingAllDatasParams
} from './interface';
import { autoGenerateTask, checkGenerateTask, getFlowList, loadSourceConfig, loadSourceTree } from './service';

export const $ImpSdk = {
  /**
   * 业务流帮助
   */
  async flowHelp({
    bizCode,
    bizType,
    orgId,
    tenantId,
    title,
    width,
    height,
    contractTypes
  }: IFlowParams): Promise<ArrayReturnType> {
    const result = await getFlowList({ bizCode, orgId, tenantId, bizType: bizType || 0, contractTypes });
    if (!result) {
      return [false, null];
    }
    if (result.length) {
      if (result.length === 1) {
        return [true, result[0]];
      }
      const { helpConfig } = getGlobalConfig().default;
      return new Promise((resolve) => {
        showModal({
          title: title || '选择业务流',
          width: width || helpConfig.width,
          height: height || helpConfig.height,
          content: <FlowHelp dataSource={result} />,
          async onOk(ins) {
            const result = await ins.getApi().getResult();
            if (result) {
              ins.destroy();
              resolve([true, result]);
            }
          },
          onCancel(ins) {
            ins.destroy();
            resolve([false, {}]);
          }
        });
      });
    }
    return [false, null];
  },
  /**
   * 引用来源（imp拉）
   */
  async citeSource(params: ICiteSourceParams): Promise<ArrayReturnType<IObject>> {
    const errorReturn: ArrayReturnType<IObject> = [false, {}];
    const {
      title,
      btnMessage = true,
      width,
      height,
      bizCode,
      tableName,
      busData,
      flowCode,
      sourceBizCode,
      detailTables,
      autoFill = false,
      defaultSelectedKeys = []
    } = params;
    if (!bizCode) {
      iup.alert('参数错误');
      return errorReturn;
    }
    const { helpConfig } = getGlobalConfig().default;
    const [sourceTree, sourceNodes] = await loadSourceTree({ flowCode, bizCode, tableName, sourceBizCode });
    if (!sourceNodes.length) {
      if (btnMessage) {
        iup.alert(iup.isString(sourceTree) ? sourceTree : '未配置数据来源！');
      }
      return errorReturn;
    }
    const sourceId = sourceNodes[0].key;
    const {
      columns = [],
      queryItems = [],
      popupName,
      allowMultiSelect,
      popupMode,
      masterQueryItems,
      masterColumns,
      masterFormId,
      treeFieldConfig,
      treeField
    } = await loadSourceConfig({
      sourceId: sourceId.split('_')[1]
    });

    let modalTitle = title || '选择来源';
    // 单来源-->popupName
    if (sourceNodes.length <= 1) {
      modalTitle = popupName;
    }
    return new Promise((resolve) => {
      showModal({
        title: modalTitle,
        width: width || helpConfig.width,
        height: height || helpConfig.height,
        content: (
          <SourceHelp
            sourceTree={sourceTree}
            detailTables={detailTables}
            defaultSourceCfg={{
              columns,
              queryItems,
              sourceId,
              allowMultiSelect,
              popupMode,
              subTableTitle: popupName,
              masterQueryItems,
              masterColumns,
              masterFormId,
              treeFieldConfig,
              treeField
            }}
            flowCode={flowCode}
            busData={busData}
            sourceCount={sourceNodes.length}
            defaultSelectedKeys={defaultSelectedKeys}
          />
        ),
        async onOk(ins) {
          const impData = await ins.getApi().getResult();
          if (impData) {
            ins.destroy();
            // 回填业务数据到业务表单
            autoFill &&
              iup.updateState((updater: any) => {
                updater.data?.setProps((pd: any) => {
                  const newData = { ...pd };
                  Object.keys(newData).forEach((k) => {
                    if (impData[k]?.length) {
                      // 子表新增主表覆盖
                      newData[k] = k.endsWith('VoList') ? (newData[k] || []).concat(impData[k]) : impData[k][0];
                    }
                  });
                  return newData;
                });
              });
            resolve([true, impData]);
          }
        },
        onCancel(ins) {
          ins.destroy();
          resolve(errorReturn);
        }
      });
    });
  },
  /**
   * 生成目的单（imp推）
   */
  async pushBill(params: IPushBillParams): Promise<ArrayReturnType<string | string[]>> {
    const {
      flowCode: paramFlowCode,
      bizCode,
      instanceId,
      bizId,
      orgId,
      tenantId,
      width,
      height,
      title,
      targetBizCode,
      autoOpen = false,
      contractTypes,
      tableType
    } = params;
    let flowCode = paramFlowCode;
    if (!flowCode) {
      const [rc, result] = await $ImpSdk.flowHelp({
        bizCode,
        bizType: 1,
        orgId,
        tenantId,
        width,
        height,
        contractTypes,
        tableType
      });
      if (rc) {
        flowCode = result.flowCode;
      }
    }
    if (!flowCode) {
      iup.alert('未配置生成目的单的业务流!');
      return [false, ''];
    }

    // 获取单据转换列表
    const [success, result] = await iup.request.bodyWithArray({
      url: '/iup-rule-engine/bizflow/rulebiz/findPushConversionList',
      data: {
        flowCode,
        bizCode,
        targetBizCode
      }
    });
    if (!success) {
      iup.alert(result);
      return [false, ''];
    }

    if (!result.length) {
      iup.alert('未配置生成目的单的转换关系！');
      return [false, ''];
    }

    let convertInfo: any = null;
    if (result.length > 1) {
      const [r, d] = await new Promise<[boolean, any]>((resolve) => {
        const { helpConfig } = getGlobalConfig().default;
        showModal({
          title: title || '选择单据转换关系',
          width: width || helpConfig.width,
          height: height || helpConfig.height,
          content: <ConvertListHelp dataSource={result} />,
          async onOk(ins) {
            const result = await ins.getApi().getResult();
            if (result) {
              ins.destroy();
              resolve([true, result]);
            }
          },
          onCancel(ins) {
            ins.destroy();
            resolve([false, void 0]);
          }
        });
      });
      if (r) {
        convertInfo = d;
      } else {
        return [false, '取消选择单据转换关系'];
      }
    } else {
      convertInfo = result[0];
    }

    // 获取推单据信息
    const [s, data] = await iup.request.bodyWithArray({
      url: '/iup-rule-engine/bizflow/rulebiz/pushBillForOpen',
      data: {
        flowCode,
        instanceId,
        bizCode,
        bizId,
        ruleIdList: [convertInfo.id]
      }
    });

    const { generateTask, needUser } = await checkGenerateTask({ flowCode, bizCode, instanceId, bizId });
    // 是否需要生成代办任务
    if (generateTask) {
      const generateTaskParams: any = { flowCode, bizCode, bizId, instanceId };
      // 是否需要选择用户
      if (needUser) {
        const taskUserRows = await iup.external.openHelp({
          type: 'UserHelp',
          title: '指定执行人'
        });
        generateTaskParams.userNos = !!taskUserRows?.value ? [taskUserRows.value] : [];
        // 不选择人员，结束流程
        if (!taskUserRows?.value) {
          return [false, []];
        }
      }
      // 生成任务
      const taskFlag = await autoGenerateTask(generateTaskParams);
      if (taskFlag) {
        iup.message('生成代办任务成功！', 'success');
        return [true, []];
      }
      // 生成代办任务无需其他操作
      return [false, []];
    }

    if (s) {
      const list = iup.isArray(data) ? data : [data];
      const editUrlList: string[] = [];
      list.forEach((r) => {
        const editUrl = iup.handleUrl(r.editUrl, { cacheKey: r.cacheKey });
        if (autoOpen) {
          iup.open(editUrl, { AppTitle: `${convertInfo.targetBizName}_新增`, oType: OType.Add });
        }
        editUrlList.push(editUrl);
      });
      return [true, editUrlList];
    } else {
      iup.alert(data);
      return [false, ''];
    }
  },
  /**
   * 获取推单据数据
   * @param cacheKey 单据数据缓存key
   * @returns
   */
  async getPushBillData({
    cacheKey,
    autoFill = false
  }: { cacheKey?: string; autoFill?: boolean } = {}): Promise<IObject> {
    const key = cacheKey || iup.getQueryValue('cacheKey');
    const [success, result] = await iup.request.postWithArray({
      url: `/iup-rule-engine/bizflow/rulebiz/getPushBillData`,
      data: {
        cacheKey: key
      }
    });
    if (success) {
      const impData = result.reduce((p, d) => {
        const tmp = { ...p, [d.tableName]: d.data };
        if (d.modelName) {
          tmp[d.modelName] = d.data;
        }
        return tmp;
      }, {});
      // 回填业务数据到业务表单
      autoFill &&
        iup.updateState((updater: any) => {
          updater.data?.setProps((pd: any) => {
            const newData = { ...pd };
            Object.keys(newData).forEach((k) => {
              if (impData[k]?.length) {
                newData[k] = k.endsWith('VoList') ? impData[k] : impData[k][0];
              }
            });
            return newData;
          });
        });
      return impData;
    }
    iup.alert(result);
    return {};
  },
  /**
   * 业务流实例查看
   */
  showFlowInstance(params: IShowFlowInstance) {
    const { appTitle, bizCode, bizId, instanceId } = params as any;
    if (!instanceId && (!bizCode || !bizId)) {
      iup.alert('参数错误，业务类型和业务主键不能为空！');
      return;
    }
    if (!instanceId) {
      iup.alert('参数错误，流程实例不能为空！');
      return;
    }
    iup.open('/business/flowmanage/detail', {
      microAppName: 'bre',
      AppTitle: appTitle || '业务流实例查看',
      oType: OType.View,
      instanceId,
      bizCode,
      id: bizId
    });
  },
  /**
   * 来源引用引用数据时支持不弹出数据选择窗口，直接返回所有数据

   */
  async mappingAllDatas(params: MappingAllDatasParams): Promise<ArrayReturnType> {
    const [success, result] = await iup.request.bodyWithArray({
      url: '/iup-rule-engine/helpInfo/mappingAllDatas',
      data: {
        ...params
      }
    });
    if (!success) {
      iup.alert(result);
      return [false, ''];
    } else if (success) {
      const list = iup.isArray(result) ? result : [result];
      return [true, list];
    }
    return [false, null];
  },
  /**
   * 校验规则提示窗
   */
  showCheckRuleInfo({ dataSource, isView, saveDraft, onContinue, title, width, height }: ICheckRuleInfoParams) {
    const { helpConfig } = getGlobalConfig().default;
    // 数据源转化
    const updatedData = dataSource?.map((item) => ({
      ...item,
      returnTips: item.returnTips.map((tip) => ({
        ...tip,
        ruleName: item.ruleName,
        ruleFlag: item.ruleFlag
      }))
    }));

    // 展示的数据列
    const returnTips = updatedData.flatMap((item) => item.returnTips);
    const hasForbiddenRule = returnTips.some((item) => item.retFlag === 'forbid');
    const hasIgnoreRule = returnTips.every((item) => item.retFlag === 'ignore');

    if (hasIgnoreRule && !isView) {
      return '无需弹窗'; // 无需弹窗
    }

    return new Promise((resolve) => {
      const ins = showModal({
        title: title || '业务管控规则',
        width: width || helpConfig.width,
        height: height || helpConfig.height,
        content: <ShowCheckRuleInfo dataSource={returnTips} />,
        footer: isView ? (
          <div
            style={{
              display: 'flex',
              alignItems: 'center',
              justifyContent: 'flex-end',
              padding: '16px'
            }}
          >
            <Button
              type="primary"
              style={{ marginLeft: 10 }}
              onClick={() => {
                ins.destroy();
              }}
            >
              确认
            </Button>
          </div>
        ) : (
          true
        ),
        footerRight: !hasForbiddenRule && (
          <Button
            type="primary"
            style={{ marginLeft: 10 }}
            onClick={() => {
              onContinue && onContinue(ins);
            }}
          >
            继续
          </Button>
        ),
        okText: '保存草稿',
        async onOk(ins) {
          saveDraft && saveDraft(ins);
        },
        onCancel(ins) {
          ins.destroy();
          resolve([false, void 0]);
        }
      });
    });
  },
  /**
   * 结束待办任务
   * @param params  { taskId: string }
   * @returns
   */
  async closeTaskByTaskId(params: { taskId: string }): Promise<boolean> {
    const { taskId } = params;
    if (!taskId) return true;
    const { code, data } = await iup.request.get({
      url: '/iup-rule-engine/flow/definition/closeTask',
      data: { taskId }
    });
    if (code !== 0) {
      iup.alert(data);
      return false;
    }
    return true;
  }
};

iup.registerExternal({
  getImpSdk() {
    return $ImpSdk;
  }
});
